﻿/*
 * @author: wizardc
 */

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Dou.UI
{
    /// <summary>
    /// 事件阻挡和向下层穿透
    /// 仅适用于特定的场景，目前有如下的问题：
    /// 1.遮挡UI的GO不能有任何的可接收事件的`Graphic`子或孙UI，否则执行`ExecuteHierarchy`时又会调用到自身，出现死循环；
    /// 2.PointEnter和PointExit方法，只能移出遮挡UI时才会触发，所以子UI对该事件的接收并不是子UI自身的实际尺寸；
    /// 3. 拖拽存在问题；
    /// </summary>
    public class EventBlock : MonoBehaviour, IPointerMoveHandler, IPointerEnterHandler, IPointerExitHandler,
        IPointerDownHandler, IPointerUpHandler, IPointerClickHandler, IBeginDragHandler, IInitializePotentialDragHandler,
        IDragHandler, IEndDragHandler, IDropHandler, IScrollHandler
    {
        private static List<RaycastResult> _results = new List<RaycastResult>();

        public bool allowPointMove = false;
        public bool allowPointEnter = false;
        public bool allowPointExit = false;
        public bool allowPointDown = false;
        public bool allowPointUp = false;
        public bool allowPointClick = false;
        public bool allowBeginDrag = false;
        public bool allowInitializePotentialDrag = false;
        public bool allowDrag = false;
        public bool allowEndDrag = false;
        public bool allowDrop = false;
        public bool allowScroll = false;

        private void ToBottomHierarchy<T>(PointerEventData eventData, ExecuteEvents.EventFunction<T> functor) where T : IEventSystemHandler
        {
            EventSystem.current.RaycastAll(eventData, _results);
            for (int i = 0; i < _results.Count; i++)
            {
                var result = _results[i];
                if (result.gameObject != gameObject)
                {
                    ExecuteEvents.ExecuteHierarchy(result.gameObject, eventData, functor);
                    break;
                }
            }
        }

        public void OnPointerMove(PointerEventData eventData)
        {
            if (allowPointMove)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.pointerMoveHandler);
            }
        }

        public void OnPointerEnter(PointerEventData eventData)
        {
            if (allowPointEnter)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.pointerEnterHandler);
            }
        }

        public void OnPointerExit(PointerEventData eventData)
        {
            if (allowPointExit)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.pointerExitHandler);
            }
        }

        public void OnPointerDown(PointerEventData eventData)
        {
            if (allowPointDown)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.pointerDownHandler);
            }
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            if (allowPointUp)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.pointerUpHandler);
            }
        }

        public void OnPointerClick(PointerEventData eventData)
        {
            if (allowPointClick)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.pointerClickHandler);
            }
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            if (allowBeginDrag)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.beginDragHandler);
            }
        }

        public void OnInitializePotentialDrag(PointerEventData eventData)
        {
            if (allowInitializePotentialDrag)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.initializePotentialDrag);
            }
        }

        public void OnDrag(PointerEventData eventData)
        {
            if (allowDrag)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.dragHandler);
            }
        }

        public void OnEndDrag(PointerEventData eventData)
        {
            if (allowEndDrag)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.endDragHandler);
            }
        }

        public void OnDrop(PointerEventData eventData)
        {
            if (allowDrop)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.dropHandler);
            }
        }

        public void OnScroll(PointerEventData eventData)
        {
            if (allowScroll)
            {
                ToBottomHierarchy(eventData, ExecuteEvents.scrollHandler);
            }
        }
    }
}
